package com.google.code.p.restrpc.client.loadbalance;

import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

import com.google.code.p.restrpc.RestfulRequest;
import com.google.code.p.restrpc.RpcRequest;

/**
 * @author dz
 */
public class CachedRoundRobinLoadBalanceStrategy extends
                                                AbstractLoadBalanceStrategy {
    
    private final ConcurrentMap<String, AtomicInteger> selectedHistory = new ConcurrentHashMap<String, AtomicInteger>();
    
    @Override
    protected int doSelect(String serviceName,
                           String methodName,
                           RpcRequest[] requests) {
        if (requests == null || requests.length == 0) {
            return -1;
        }
        
        if (requests.length == 1) {
            return 0;
        }
        
        String key = serviceName;
        AtomicInteger lastSelected = selectedHistory.get(key);
        if (lastSelected == null) {
            selectedHistory.putIfAbsent(key,
                                        new AtomicInteger(Integer.MAX_VALUE));
            lastSelected = selectedHistory.get(key);
        }
        
        // if the counter is not initialized,initialize to the random value
        lastSelected.compareAndSet(Integer.MAX_VALUE,
                                   new Random().nextInt(requests.length));
        return lastSelected.getAndIncrement() % requests.length;
    }
    
    public static void main(String[] args) {
        LoadBalanceStrategy loadBalance = new RoundRobinLoadBalanceStrategy();
        for (int i = 0; i < 100; i++) {
            System.out.println(i + ":"
                               + loadBalance.select("testService",
                                                    "testMethod",
                                                    new RestfulRequest[4]));
        }
    }
}
